package main

import(
    "errors"
    "log"
    "net/rpc"  // rpc 主服务
    "net"  // net 监听 tcp 端口
    "net/rpc/jsonrpc"  // jsonrpc 解析请求参数
)

// 官方示例 Arith
type Args struct {  // 参数结构体, 通用两个Method
	A, B int
}

type Quotient struct {  // Divide 方法特有结构体
	Quo, Rem int
}

type Arith int  // 声明一个 int 型结构体

func (t *Arith) Multiply(args *Args, reply *int) error {  // 为 Arith 添加 Multiply 方法 (Method)
	*reply = args.A * args.B
	return nil
}

func (t *Arith) Divide(args *Args, quo *Quotient) error {  // 为 Arith 添加 Divide 方法 (Method)
	if args.B == 0 {
		return errors.New("divide by zero")
	}
	quo.Quo = args.A / args.B
	quo.Rem = args.A % args.B
	return nil
}

// 个人实验, Human
type Human struct{
    Name string
    Age int
}

func (t *Human) GetAge(args *Human, reply *int) error {  // 为 Human 添加 GetAge 方法 (Method)
    *reply = args.Age
    return nil
}

func (t *Human) GetName(args *Human, reply *string) error {  // 为 Human 添加 GetName 方法 (Method)
    *reply = args.Name
    return nil
}

func main(){
    arith := new(Arith)  // 实例化(生成一个自定义结构体变量)一个类似类的东西
    rpc.Register(arith)  // 在 rpc 上注册
    human := new(Human)
    rpc.Register(human)
    l, e := net.Listen("tcp", ":3999")  // 监听 tcp 的端口和 ip
    if e != nil {
    	log.Fatal("listen error:", e)
    }
    defer l.Close()
    rpcserver := rpc.NewServer()  // 新建一个 rpcServer
    rpcserver.Register(arith)  // 注册之前创建的对象到 rpc 上
    rpcserver.Register(human)
    for{  // 循环接受新的请求
        c, e := l.Accept()  // 接受一个新请求
        if e != nil{
            log.Fatal("Accept Error \n")
        }
        jsoncodec := jsonrpc.NewServerCodec(c)  // 使用 jsoncodec 解析请求参数
        rpcserver.ServeCodec(jsoncodec)   // rpc 对该请求进行服务
    }
}
